from flask import request, session
from app import db
from . import bp
from sqlalchemy.exc import IntegrityError
from hashlib import md5
from AuthComponent import auth_required
from utils import respond, ERRORCODES
from .models import User
from requests import get
from config import Config
import re


@auth_required()
@bp.route("/register", methods=["POST"])
def register():
    try:
        data = request.json
        username = data["username"]
        password = data["password"]
        # 检查密码强度
        if (
            len(password) < 8
            or sum(
                (
                    bool(re.search(validator, password))
                    for validator in ("[A-Z]", "[a-z]", "\d", "[^a-zA-Z0-9]")
                )
            )
            < 2
        ):
            return respond(None, "密码强度不足。", ERRORCODES.WEAK_PASSWORD)

        password = md5(password.encode()).hexdigest()
        new_user = User(username=username, password=password)
        db.session.add(new_user)
        db.session.commit()
        return respond({"user_id": new_user.uuid}, "注册成功。", ERRORCODES.CREATED)
    except IntegrityError:
        return respond(None, "用户已存在。", ERRORCODES.USER_EXISTS)
    except KeyError:
        return respond(None, "必须指定用户名或密码。", ERRORCODES.MISSING_PARAMETERS)


@auth_required()
@bp.route("/login", methods=["POST"])
def login():
    try:
        if session.get("user"):
            return respond(None, "已登录。", ERRORCODES.FORBIDDEN)

        data = request.json
        password = md5(data["password"].encode()).hexdigest()
        user = User.query.filter_by(
            username=data["username"], password=password
        ).first()

        if user:
            session["user"] = user.uuid
            return respond({"user_id": user.uuid}, "登录成功。")
        else:
            return respond(None, "用户名或密码错误。", ERRORCODES.INVALID_AUTH_INFO)
    except KeyError:
        return respond(None, "必须指定用户名或密码。", ERRORCODES.MISSING_PARAMETERS)


@auth_required()
@bp.route("/logout", methods=["POST"])
def logout():
    if "user" in session:
        session.pop("user")
        return respond(None, "登出成功。")
    else:
        return respond(None, "未登录。", ERRORCODES.UNAUTHORIZED)


@auth_required()
@bp.route("/wx_login", methods=["POST"])
def wx_login():
    data = get(
        "https://api.weixin.qq.com/sns/jscode2session",
        params={
            "appid": Config.WX_APP_ID,
            "secret": Config.WX_APP_SECRET,
            "js_code": request.json.get("code"),
            "grant_type": "authorization_code",
        },
    ).json()

    if data["errcode"] != 0:
        return respond(
            None, data.get("errmsg", "微信登录失败。"), ERRORCODES.WX_LOGIN_FAILED
        )

    user = User.query.filter_by(wxid=data["openid"]).first()
    if not user:
        user = User(wxid=data["openid"])
        db.session.add(user)
        db.session.commit()
    session["user"] = user.uuid

    return respond(
        {
            "user_id": user.uuid,
            "openid": data["openid"],
        },
        "登录成功。",
    )


@auth_required()
@bp.route("/update_password", methods=["POST"])
def update_password():
    try:
        if "user" not in session:
            return respond(None, "未登录。", ERRORCODES.UNAUTHORIZED)

        data = request.json
        current_password = md5(data["current_password"].encode()).hexdigest()
        new_password = data["new_password"]

        user = User.query.filter_by(uuid=session["user"]).first()
        if not user:
            return respond(None, "用户未找到。", ERRORCODES.UNAUTHORIZED)

        if user.password != current_password:
            return respond(None, "当前密码错误。", ERRORCODES.INVALID_AUTH_INFO)

        if (
            len(new_password) < 8
            or sum(
                (
                    bool(re.search(validator, new_password))
                    for validator in ("[A-Z]", "[a-z]", "\d", "[^a-zA-Z0-9]")
                )
            )
            < 2
        ):
            return respond(None, "新密码强度不足。", ERRORCODES.WEAK_PASSWORD)


        user.password = md5(new_password.encode()).hexdigest()
        db.session.commit()

        return respond({"message": "密码更新成功。"})

    except KeyError:
        return respond(None, "必须指定当前密码和新密码。", ERRORCODES.MISSING_PARAMETERS)
    except Exception as e:
        db.session.rollback()
        return respond(
            None, f"密码更新时发生错误: {str(e)}", ERRORCODES.INTERNAL_SERVER_ERROR
        )